#pragma once
#include "Callback.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include <cstdio>
#include <functional>

struct Message {
	int port_num;
	char *payload;
	size_t length;
};

class SerialMessageQueueManager {
public:
	// 构造函数：创建 SerialMessageQueueManager 对象
	// queueLength : 队列长度，默认 10
	explicit SerialMessageQueueManager(size_t queueLength = 10) :
		// 成员初始化列表：直接初始化类成员 queue
		// xQueueCreate 创建一个 FreeRTOS 队列，可以存储 queueLength 个 Message 对象
		queue(xQueueCreate(queueLength, sizeof(Message))) {
		if (!queue) {
			printf("Failed to create queue!\n");
		}
	}

	~SerialMessageQueueManager() {
		running = false; // 停止消费者任务
		if (consumerTaskHandle) {
			vTaskDelete(consumerTaskHandle);
		}
		if (queue) {
			vQueueDelete(queue);
		}
	}

	// 发送消息到队列
	// msg     : 要发送的消息对象
	// timeout : 等待队列可用的最大时间，默认 500 毫秒
	// 返回值  : true 表示发送成功，false 表示队列不存在或发送失败
	bool send(const Message &msg, TickType_t timeout = pdMS_TO_TICKS(500)) {

		Message newMsg = msg;
		// 分配堆内存，+1 预留安全空间
		newMsg.payload = static_cast<char *>(malloc(msg.length + 1));
		if (!newMsg.payload)
			return false;

		memcpy(newMsg.payload, msg.payload, msg.length);
		// 方便调试用，保证有结束符
		newMsg.payload[msg.length] = '\0';

		// 把深拷贝的消息发进队列
		return queue && (xQueueSend(queue, &newMsg, timeout) == pdPASS);
	}

	// 启动消费者任务
	// cb       : 用户传入的回调函数，用于处理队列收到的消息
	// taskName : FreeRTOS 任务名字，默认为 "Consumer"
	// stackSize: 任务栈大小，单位字节，默认为 2048
	// priority : 任务优先级，默认为 5
	void startConsumer(const Callback<void, Message>::function &cb, const char *taskName = "Consumer", uint16_t stackSize = 2048, UBaseType_t priority = 5) {
		callback.setCallback(cb);

		// 标记消费者任务正在运行
		// running 是一个类成员布尔值，用于控制消费者任务循环是否继续
		running = true;

		// 创建 FreeRTOS 任务
		// consumerTaskWrapper 是静态成员函数，用于作为任务入口函数
		// taskName: 任务名字
		// stackSize: 任务栈大小
		// this: 将当前对象指针传入任务，这样任务可以访问类的成员和回调
		// priority: 任务优先级
		// &consumerTaskHandle: 保存创建任务的句柄，以便后续管理（删除或挂起）
		xTaskCreate(consumerTaskWrapper, taskName, stackSize, this, priority, &consumerTaskHandle);
	}

private:
	QueueHandle_t queue{nullptr};
	TaskHandle_t consumerTaskHandle{nullptr};
	Callback<void, Message> callback;
	bool running{false};

	// 消费者任务静态函数
	// FreeRTOS 任务入口函数必须是静态函数或全局函数
	static void consumerTaskWrapper(void *arg) {
		// 将传入的参数还原为 SerialMessageQueueManager 指针
		auto mgr = static_cast<SerialMessageQueueManager *>(arg);
		Message msg;

		// 循环读取队列消息，直到 running = false
		while (mgr->running) {
			// 阻塞等待队列消息，portMAX_DELAY 表示无限等待
			if (mgr->queue && xQueueReceive(mgr->queue, &msg, portMAX_DELAY) == pdPASS) {

				// 收到消息后，调用用户注册的回调函数处理消息
				// 注意：这里把 msg 传给回调时，回调函数不要 free()
				mgr->callback.callCallback(msg);

				// 释放消息中的 payload，避免内存泄漏
				if (msg.payload) {
					free(msg.payload);
					msg.payload = nullptr; // 防止野指针
				}
			}
		}
		// 退出循环时删除当前任务
		vTaskDelete(nullptr);
	}
};
